package com.spic.system.activiti.controller;


import com.github.pagehelper.Page;
import com.spic.common.core.utils.SecurityUtils;
import com.spic.common.core.utils.StringUtils;
import com.spic.common.core.web.controller.BaseController;
import com.spic.common.core.web.domain.AjaxResult;
import com.spic.common.core.web.page.PageDomain;
import com.spic.common.core.web.page.TableDataInfo;
import com.spic.common.core.web.page.TableSupport;
import com.spic.system.activiti.domain.dto.ActTaskDTO;
import com.spic.system.activiti.domain.dto.ActWorkflowFormDataDTO;
import com.spic.system.activiti.domain.dto.TaskTodoDTO;
import com.spic.system.activiti.enums.BusinessStatusEnum;
import com.spic.system.activiti.service.IActTaskService;
import com.spic.system.activiti.service.IBusinessStatusService;
import com.spic.system.activiti.service.IMyTaskService;
import com.spic.system.activiti.utils.PageUtils;
import com.spic.system.api.domain.ActTaskStartDto;
import com.spic.system.api.domain.HiddenTodoTask;
import com.spic.system.domain.vo.DoTaskParam;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/task")
public class TaskController extends BaseController {
    @Autowired
    private IMyTaskService mytaskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IActTaskService actTaskService;

    @Autowired
    private IBusinessStatusService businessStatusService;

    /**
     * 启动工作流
     * @param dto
     * @return
     */
    @PostMapping("/start")
    public AjaxResult startInstance(@RequestBody ActTaskStartDto dto){
        return AjaxResult.success(mytaskService.startInstance(dto));
    }

    @GetMapping("/deleteProcessInstance")
    public AjaxResult deleteProcessInstance (String processInstanceId){
        runtimeService.deleteProcessInstance(processInstanceId,"用户撤销");
        businessStatusService.updateStateByInstanceId(processInstanceId, BusinessStatusEnum.CANCEL);
        historyService.deleteHistoricProcessInstance(processInstanceId);
        return AjaxResult.success();
    }

    /**
     * 获取我的待办
     * @return todos 待办列表
     */
    @GetMapping("todos")
    public AjaxResult getTodos(TaskTodoDTO taskTodoDTO) {
        AjaxResult result = mytaskService.getTodos(taskTodoDTO);
        return result;
    }

    /**
     * 完成任务
     * @param taskId 任务ID
     */
    @PostMapping("complete/{taskId}")
    public AjaxResult completeTask(@PathVariable("taskId")String taskId) {
        mytaskService.completeTask(taskId);
        return AjaxResult.success();
    }

    /**
     * 带评论完成任务
     * @param taskId
     * @param params  获取form 审批意见表单值
     *
     *     问题和说明：
     *        1.两个并行审批节点同时指定下一节点人时 会覆盖
     *        2.侯选人节点 必须在上一个节点指定
     *        3.每个节点配置审批人时都是唯一的（流程图配置）；taskMap对象是定义下个候选人的map：key：表示节点的变量 value:表示候选人
     *        4.每个taskKey节点也是唯一(在流程图配置)，提前定义在前端页面上，根据当前taskKey进行判断，显示当前审批表单
     *        5.意见表单（审批人审批、各种时间）的值如何入库？更新业务表单？
     */
    @PostMapping("completeWithComment/{taskId}")
    public AjaxResult completeWithComment(@PathVariable("taskId")String taskId, @RequestBody DoTaskParam taskParam) {
        mytaskService.completeWithComment(taskId, taskParam);
        return AjaxResult.success();
    }

    @GetMapping("/back/nodes")
    public AjaxResult getBackNodes(@RequestParam String taskId) {
        try {
            String userId = SecurityUtils.getUserId()+"";
            Task task = taskService.createTaskQuery()
                    .taskId(taskId)
                    .taskAssignee(userId)
                    .singleResult();
            if( task == null ) {
                return AjaxResult.error("没有此任务或不是该任务办理人");
            }
            // 查询历史任务节点
           /* List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .list();*/
            // 不把当前节点查询出来, 没有办理完的节点不查询，每条数据都有一个唯一值，我们使用随机数
            String sql =  "select rand() AS ID_, t2.* from " +
                    " ( select distinct t1.TASK_DEF_KEY_, t1.NAME_ from " +
                    "  ( select ID_, RES.TASK_DEF_KEY_, RES.NAME_, RES.START_TIME_, RES.END_TIME_ " +
                    "   from ACT_HI_TASKINST RES " +
                    "   WHERE RES.PROC_INST_ID_ = #{processInstanceId} and TASK_DEF_KEY_ != #{taskDefKey}" +
                    "   and RES.END_TIME_ is not null order by RES.START_TIME_ asc " +
                    "  ) t1 " +
                    " ) t2";

            List<HistoricTaskInstance> list = historyService.createNativeHistoricTaskInstanceQuery()
                    .sql(sql)
                    .parameter("processInstanceId", task.getProcessInstanceId())
                    .parameter("taskDefKey", task.getTaskDefinitionKey()) // 不把当前节点查询出来
                    .list();

            List<Map<String, Object>> records = new ArrayList<>();

            for (HistoricTaskInstance hti : list) {
                Map<String, Object> data = new HashMap<>();
                //pc 端使用 返回
                data.put("activityId", hti.getTaskDefinitionKey());
                data.put("activityName", hti.getName());
                //app 要求返回
                data.put("value", hti.getTaskDefinitionKey());
                data.put("text", hti.getName());
                records.add(data);
            }

            return AjaxResult.success(records);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("查询驳回节点失败：" + e.getMessage());
        }
    }

    /**
     * 根据任务id获取业务id
     *
     * @param taskId
     * @param
     */
    @GetMapping("/{taskId}/businessKey")
    public String getBusinessKey(@PathVariable("taskId") String taskId) {
        //1.使用任务id查询任务对象task
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //2.使用任务ID，获取实例ID
        String processInstanceId = task.getProcessInstanceId();
        //3.使用流程实例，查询
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //4.使用流程实例对象获取BusinessKey
        String businessKey = pi.getBusinessKey();
        return businessKey;
    }

    //获取我的代办任务
    @GetMapping(value = "/list")
    public TableDataInfo getTasks() {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Page<ActTaskDTO> hashMaps = actTaskService.selectProcessDefinitionList(pageDomain);
         return getDataTable(hashMaps);
    }


    //渲染表单
    @GetMapping(value = "/formDataShow/{taskID}")
    public AjaxResult formDataShow(@PathVariable("taskID") String taskID) {

        return AjaxResult.success(actTaskService.formDataShow(taskID));
    }

    //保存表单
    @PostMapping(value = "/formDataSave/{taskID}")
    public AjaxResult formDataSave(@PathVariable("taskID") String taskID,
                                   @RequestBody   List<ActWorkflowFormDataDTO> formData ) throws ParseException {
        return toAjax(mytaskService.formDataSave(taskID, formData));
    }

    /**
     * 驳回方法
     * @param taskId
     * @param targetActivityId
     * @return
     */
    @PostMapping("/back")
    public AjaxResult backProcess(@RequestParam String taskId,
                                  @RequestParam String targetActivityId) {
        return mytaskService.backProcess(taskId, targetActivityId);
    }


    /**
     * 获取隐患代办待办列表
     * @return todos 待办列表
     */
    @GetMapping("/hiddenTodos")
    public AjaxResult getHiddenTodos(HiddenTodoTask hiddenTodoTask) {
        Map<String ,Object> map = new HashMap<>();
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        List<HiddenTodoTask> hiddenTodos = mytaskService.getHiddenTodos(hiddenTodoTask);

        if(StringUtils.isNotEmpty(hiddenTodoTask.getHazardLevel())){
            map.put("hazardType",hiddenTodoTask.getHazardLevel())         ;
            hiddenTodos = hiddenTodos.stream().filter(f->f.getHazardLevel().equals(hiddenTodoTask.getHazardLevel())).collect(Collectors.toList());
        }


        List<HiddenTodoTask> list = PageUtils.startPage(hiddenTodos, pageNum, pageSize); //分页后数据
        Integer count = hiddenTodos.size();
        map.put("total", count);
        map.put("list", list);
        return AjaxResult.success(map);
    }

    /**
     * 根据流程实例id获取流程任务当前节点key信息列表
     */
    @PostMapping("/getTaskInfoList")
    public AjaxResult getTaskInfoList(@RequestBody List<String> list) {
        List<String> taskList = mytaskService.getTaskInfoList(list);
        return AjaxResult.success(taskList);
    }
    @GetMapping("/getMulitInstanceTask/{processInstanceId}/{definitonKey}")
    public AjaxResult getMulitInstanceTask(@PathVariable("processInstanceId") String processInstanceId,@PathVariable("definitonKey") String definitonKey){
        List<String> tasks = mytaskService.getMulitInstanceTask(processInstanceId,definitonKey);
        return AjaxResult.success(tasks);
    }

    @GetMapping("/getRunTaskInstanceTask/{processInstanceId}")
    public AjaxResult getRunTaskInstanceTask(@PathVariable("processInstanceId") String processInstanceId){
        List<String> tasks = mytaskService.getRunTaskInstanceTask(processInstanceId);
        return AjaxResult.success(tasks);
    }
}
